#ifndef napyr2_Call_H
#define napyr2_Call_H

// *****************************************************************************************
//
// NAPYR2 (http://p-nand-q.com/python/napyr.html)
//
// Copyright (c) 2014, Gerson Kurz
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
// 
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 
// 2. Redistributions in binary form must reproduce the above copyright notice, this
//    list of conditions and the following disclaimer in the documentation and/or other
//    materials provided with the distribution.
// 
// 3. Neither the name of the copyright holder nor the names of its contributors may
//    be used to endorse or promote products derived from this software without
//    specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// *****************************************************************************************

#include "napyr2.h"
#include <string>
#include <vector>

namespace napyr2 // begins here
{
#pragma warning( push )
#pragma warning( disable: 4251 )

class PythonRuntime;
class PythonObject;

class NAPYR2_API PythonCall
    {
    public:
        PythonCall( PythonRuntime* pPythonRuntime, LPCSTR name );
		virtual ~PythonCall();
    
    private:
        PythonCall( const PythonCall& objectSrc );
        PythonCall& operator=( const PythonCall& objectSrc );
    
    public:
        void Add( const PythonObject& value );

		template <typename T> bool Call( T& value )
		{
			PythonObject po;
			if( Call( po ) )
			{	
				if( po.Get( value ) )
				{
					return true;
				}
			}
			return false;
		}

		template <typename T> T CallAndReturn( const T& initialValue )
		{
			T result(initialValue);
			PythonObject po;
			if( Call( po ) )
			{	
				if( po.Get( result ) )
				{
					return result;
				}
			}
			return initialValue;
		}

        bool Call( PythonObject& result );
		bool Call();
		
	private:
		bool BuildArgs();

    private:
        PythonRuntime* m_pPythonRuntime;
		std::vector<PyObject*> m_args;
        LPCSTR m_lpszName;
		PyGILState_STATE m_GIL;
        PyObject* m_pyFunc;
        PyObject* m_pyArgs;
    };

#pragma warning( pop )
} // namespace napyr2 ends here

#endif // napyr2_Call_H
